home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / mm / main.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  8KB  |  223 lines

  1. /* This file contains the main program of the memory manager and some related
  2.  * procedures.  When MINIX starts up, the kernel runs for a little while,
  3.  * initializing itself and its tasks, and then it runs MM.  MM at this point
  4.  * does not know where FS is in memory and how big it is.  By convention, FS
  5.  * must start at the click following MM, so MM can deduce where it starts at
  6.  * least.  Later, when FS runs for the first time, FS makes a pseudo-call,
  7.  * BRK2, to tell MM how big it is.  This allows MM to figure out where INIT
  8.  * is.
  9.  *
  10.  * The entry points into this file are:
  11.  *   main:    starts MM running
  12.  *   reply:    reply to a process making an MM system call
  13.  *   do_brk2:    pseudo-call for FS to report its size
  14.  */
  15.  
  16. #include "mm.h"
  17. #include <minix/callnr.h>
  18. #include <minix/com.h>
  19. #include "mproc.h"
  20. #include "param.h"
  21.  
  22. FORWARD void get_work();
  23. FORWARD void mm_init();
  24.  
  25. /*===========================================================================*
  26.  *                main                         *
  27.  *===========================================================================*/
  28. PUBLIC void main()
  29. {
  30. /* Main routine of the memory manager. */
  31.  
  32.   int error;
  33.  
  34.   mm_init();            /* initialize memory manager tables */
  35.  
  36.   /* This is MM's main loop-  get work and do it, forever and forever. */
  37.   while (TRUE) {
  38.     /* Wait for message. */
  39.     get_work();        /* wait for an MM system call */
  40.     mp = &mproc[who];
  41.  
  42.       /* Set some flags. */
  43.     error = OK;
  44.     dont_reply = FALSE;
  45.     err_code = -999;
  46.  
  47.     /* If the call number is valid, perform the call. */
  48.     if (mm_call < 0 || mm_call >= NCALLS)
  49.         error = EBADCALL;
  50.     else
  51.         error = (*call_vec[mm_call])();
  52.  
  53.     /* Send the results back to the user to indicate completion. */
  54.     if (dont_reply) continue;    /* no reply for EXIT and WAIT */
  55.     if (mm_call == EXEC && error == OK) continue;
  56.     reply(who, error, result2, res_ptr);
  57.   }
  58. }
  59.  
  60.  
  61. /*===========================================================================*
  62.  *                get_work                     *
  63.  *===========================================================================*/
  64. PRIVATE void get_work()
  65. {  
  66. /* Wait for the next message and extract useful information from it. */
  67.  
  68.   if (receive(ANY, &mm_in) != OK) panic("MM receive error", NO_NUM);
  69.   who = mm_in.m_source;        /* who sent the message */
  70.   mm_call = mm_in.m_type;    /* system call number */
  71. }
  72.  
  73.  
  74. /*===========================================================================*
  75.  *                reply                         *
  76.  *===========================================================================*/
  77. PUBLIC void reply(proc_nr, result, res2, respt)
  78. int proc_nr;            /* process to reply to */
  79. int result;            /* result of the call (usually OK or error #)*/
  80. int res2;            /* secondary result */
  81. char *respt;            /* result if pointer */
  82. {
  83. /* Send a reply to a user process. */
  84.  
  85.   register struct mproc *proc_ptr;
  86.  
  87.   /* To make MM robust, check to see if destination is still alive. */
  88.   proc_ptr = &mproc[proc_nr];
  89.   if ( (proc_ptr->mp_flags&IN_USE) == 0 || (proc_ptr->mp_flags&HANGING)) return;
  90.   reply_type = result;
  91.   reply_i1 = res2;
  92.   reply_p1 = respt;
  93.   if (send(proc_nr, &mm_out) != OK) panic("MM can't reply", NO_NUM);
  94. }
  95.  
  96.  
  97. /*===========================================================================*
  98.  *                mm_init                         *
  99.  *===========================================================================*/
  100. PRIVATE void mm_init()
  101. {
  102. /* Initialize the memory manager. */
  103.  
  104.   mem_init();            /* initialize tables to all physical mem */
  105.  
  106.   /* Initialize MM's tables. */
  107.   mproc[MM_PROC_NR].mp_flags |= IN_USE;
  108.   mproc[FS_PROC_NR].mp_flags |= IN_USE;
  109.   mproc[INIT_PROC_NR].mp_flags |= IN_USE;
  110.   mproc[INIT_PROC_NR].mp_pid = INIT_PID;
  111.   procs_in_use = 3;
  112. }
  113.  
  114.  
  115. /*===========================================================================*
  116.  *                do_brk2                            *
  117.  *===========================================================================*/
  118. PUBLIC int do_brk2()
  119. {
  120. /* This "call" is made once by FS during system initialization and then never
  121.  * again by anyone.  It contains the origin and size of INIT, and the combined
  122.  * size of the 1536 bytes of unused mem, MINIX and RAM disk.
  123.  *   m1_i1 = size of INIT text in clicks
  124.  *   m1_i2 = size of INIT data in clicks
  125.  *   m1_i3 = number of bytes for MINIX + RAM DISK
  126.  *   m1_p1 = origin of INIT in clicks
  127.  */
  128.  
  129.   int mem1, mem2, mem3;
  130.   register struct mproc *rmp;
  131.   phys_clicks init_org, init_clicks, ram_base, ram_clicks, tot_clicks;
  132.   phys_clicks init_text_clicks, init_data_clicks;
  133.   phys_clicks minix_clicks;
  134.  
  135.   if (who != FS_PROC_NR) return(EPERM);    /* only FS make do BRK2 */
  136.  
  137.   /* Remove the memory used by MINIX from the memory map. */
  138.   init_text_clicks = mm_in.m1_i1;    /* size of INIT in clicks */
  139.   init_data_clicks = mm_in.m1_i2;    /* size of INIT in clicks */
  140.   init_org = (phys_clicks) mm_in.m1_p1;    /* addr where INIT begins in memory */
  141.   init_clicks = init_text_clicks + init_data_clicks;
  142.   minix_clicks = init_org + init_clicks;    /* size of system in clicks */
  143.   ram_base = alloc_mem(minix_clicks);    /* remove MINIX from map */
  144.   if (ram_base != 0)
  145.     panic("inconsistent system memory base", ram_base);
  146.  
  147.   /* Remove the memory used by the RAM disk from the memory map. */
  148.   tot_clicks = mm_in.m1_i3;        /* total size of MINIX + RAM disk */
  149.   ram_clicks = tot_clicks - minix_clicks;    /* size of RAM disk */
  150. #if (CHIP == INTEL)
  151.   /* Put RAM disk in extended memory, if any. */
  152.   if (get_mem(&ram_base, TRUE) >= ram_clicks)
  153.     goto got_base;
  154. #endif
  155.   ram_base = alloc_mem(ram_clicks);    /* remove the RAM disk from the map */
  156.   if (ram_base == NO_MEM)
  157.     panic("not enough memory for RAM disk", NO_NUM);
  158. got_base:
  159.   mm_out.POSITION = (phys_bytes) ram_base * CLICK_SIZE;    /* tell FS where */
  160.  
  161.   /* Print memory information. */
  162. #if (MACHINE == MACINTOSH)
  163.   /* Mac memory does not start at zero, so adjust the numbers */
  164.   mem1 = click_to_round_k(minix_clicks-start_click()+ram_clicks+mem_left());  
  165.   mem2 = click_to_round_k(minix_clicks-start_click());
  166. #else
  167.   mem1 = click_to_round_k(minix_clicks + ram_clicks + mem_left());  
  168.   mem2 = click_to_round_k(minix_clicks);
  169. #endif
  170.   mem3 = click_to_round_k(ram_clicks);
  171. #if (CHIP == INTEL)
  172.   printf("%c[H%c[J",033, 033);    /* go to top of screen and clear screen */
  173. #endif
  174.   printf("Memory size = %4dK     ", mem1);
  175.   printf("MINIX = %3dK     ", mem2);
  176.   printf("RAM disk = %4dK     ", mem3);
  177.   printf("Available = %dK\n\n", mem1 - mem2 - mem3);
  178.   if (mem1 - mem2 - mem3 < 32) {
  179.     printf("\nNot enough memory to run MINIX\n\n", NO_NUM);
  180.     sys_abort();
  181.   }
  182.  
  183.   /* Initialize INIT's table entry. */
  184.   rmp = &mproc[INIT_PROC_NR];
  185.   rmp->mp_seg[T].mem_phys = init_org;
  186.   rmp->mp_seg[T].mem_len  = init_text_clicks;
  187.   rmp->mp_seg[D].mem_phys = init_org + init_text_clicks;
  188.   rmp->mp_seg[D].mem_len  = init_data_clicks;
  189.   rmp->mp_seg[S].mem_phys = init_org + init_clicks;
  190. #if (CHIP == M68000)
  191.   rmp->mp_seg[T].mem_vir  = rmp->mp_seg[T].mem_phys;
  192.   rmp->mp_seg[D].mem_vir  = rmp->mp_seg[D].mem_phys;
  193.   rmp->mp_seg[S].mem_vir  = rmp->mp_seg[S].mem_phys;
  194. #else
  195.   rmp->mp_seg[S].mem_vir  = init_clicks;
  196. #endif
  197.   if (init_text_clicks != 0) rmp->mp_flags |= SEPARATE;
  198.  
  199.   return(OK);
  200. }
  201.  
  202.  
  203. /*===========================================================================*
  204.  *                get_mem                         *
  205.  *===========================================================================*/
  206. PUBLIC phys_clicks get_mem(pbase, extflag)
  207. phys_clicks *pbase;        /* where to return the base */
  208. int extflag;            /* nonzero for extended memory */
  209. {
  210. /* Ask kernel for the next chunk of memory.  'extflag' specifies the type of
  211.  * memory.  "Extended" memory here means memory above 1MB which is no good
  212.  * for putting programs in but usable for the RAM disk.  MM doesn't care
  213.  * about the locations of the 2 types of memory, except memory above 1MB is
  214.  * unreachable unless CLICK_SIZE > 16, but still usable for the RAM disk.
  215.  */
  216.   mm_out.m_type = SYS_MEM;
  217.   mm_out.DEVICE = extflag;
  218.   if (sendrec(SYSTASK, &mm_out) != OK || mm_out.m_type != OK)
  219.     panic("Kernel didn't respond to get_mem", NO_NUM);
  220.   *pbase = (phys_clicks) mm_out.POSITION;
  221.   return((phys_clicks) mm_out.COUNT);
  222. }
  223.